/**
 * @file bsp_dac.c
 * @brief DAC封装驱动
 * @author wangh (wanghuan3037@fiberhome.com)
 * @version 1.0
 * @date 2020-10-17
 * @copyright Copyright (c) 2020  烽火通信
 ***************************************************************
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2019-11-17 <td>1.0     <td>wangh     <td>内容
 * </table>
 */
#include "bsp_dac.h"
#include <stdio.h>

#undef LOG_LEVEL_
#define LOG_LEVEL_ 	LOG_LVL_ASSERT
#include "bsp_log.h"


/**
 * @brief DAC初始化
 * @param[in]  obj          dac对象
 * @param[in]  dacPin       dac引脚
 * @return int8_t 
 * - @b Success : @ref BSP_SUCCESS \n
 * - @b Fail
 * - @ref BSP_ERROR_ALREADY_INIT - 已初始化
 * - @ref BSP_ERROR_NOT_SUPPORTED - 引脚不支持
 * - @ref BSP_ERROR_INVALID_PARAM - 非法引脚
 */
int8_t DacInit(Dac_t *obj, PinNames dacPin)
{
    if (obj == NULL)
        return BSP_ERROR_INVALID_PARAM;

    if( obj->IsInitialized )
    {
        log_e( "DacInit error: has already Initialized\r\n" );
        return BSP_ERROR_ALREADY_INIT;
    }

    if( dacPin != NC )
    {
        switch (dacPin)
        {
#ifdef STM32F10X
            case PA_4: obj->channel = 1; break;
            case PA_5: obj->channel = 2; break;
#elif defined GD32F10X
            case PA_4: obj->channel = DAC0; break;
            case PA_5: obj->channel = DAC1; break;
#endif
            default:
                log_e( "DacInit error: this pin is not support DAC\r\n" );
                return BSP_ERROR_NOT_SUPPORTED;
        }
        
        GpioInit( &obj->DacPin, dacPin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
    }
    else
        return BSP_ERROR_INVALID_PARAM;

#ifdef STM32F10X
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);                  /* 使能DAC通道时钟 */
    DAC_InitTypeDef DAC_InitType;
    DAC_InitType.DAC_Trigger = DAC_Trigger_None;                         /* 不使用触发功能,TEN1=0 */
    DAC_InitType.DAC_WaveGeneration = DAC_WaveGeneration_None;           /* 不使用波形发生 */
    DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; /* 屏蔽、幅值设置 */
    DAC_InitType.DAC_OutputBuffer = DAC_OutputBuffer_Disable;            /* DAC1输出缓存关闭,BOFF1=1 */

    if( obj->channel == 1 )
    {
        DAC_Init(DAC_Channel_1, &DAC_InitType);     /* 初始化DAC通道1 */
        DAC_Cmd(DAC_Channel_1, ENABLE);             /* 使能DAC1 */
    }
    else if( obj->channel == 2 )
    {
        DAC_Init(DAC_Channel_2, &DAC_InitType);     /* 初始化DAC通道2 */
        DAC_Cmd(DAC_Channel_2, ENABLE);             /* 使能DAC2 */
    }
#elif defined GD32F10X
    rcu_periph_clock_enable( RCU_DAC );
    dac_trigger_source_config( obj->channel, DAC_TRIGGER_SOFTWARE);
    dac_trigger_enable( obj->channel );
    dac_wave_mode_config( obj->channel, DAC_WAVE_DISABLE );
    dac_output_buffer_disable( obj->channel );
    dac_enable( obj->channel );
#endif

    obj->IsInitialized = true;

    return BSP_SUCCESS;
}

/**
 * @brief DAC去初始化
 * @param[in]  obj          dac对象
 */
void DacDeInit(Dac_t *obj)
{
    if (obj && obj->IsInitialized)
    {
        obj->IsInitialized = false;
#ifdef STM32F10X
        DAC_DeInit();
#elif defined GD32F10X
        dac_deinit();
#endif
    }
}

/**
 * @brief 设置DAC通道输出电压
 * @param[in]  obj          dac对象
 * @param[in]  vol          dac输出电压（0~3.3V）
 * @return int8_t 
 * - @b Success : @ref BSP_SUCCESS \n
 * - @b Fail
 * - @ref BSP_ERROR_NO_INIT - 已初始化
 * - @ref BSP_ERROR_INVALID_PARAM - 电压越限
 */
int8_t DacSetVol( Dac_t *obj, float vol )
{
    if (obj == NULL)
        return BSP_ERROR_INVALID_PARAM;

    if ( !obj->IsInitialized )
    {
        log_e( "DacSetVol error: no Initialized\r\n" );
        return BSP_ERROR_NO_INIT;
    }

    if ((vol < 0) || (vol > 3.3))
    {
        log_e( "DacSetVol error: vol is exceed(0~3.3)\r\n" );
        return BSP_ERROR_INVALID_PARAM;
    }

    float temp = vol * 4096 / 3.3;

    // log_d( "DacSetVol %d.%02d (%d)\r\n", (uint8_t)(vol*100/100), (uint8_t)((vol*100)%100), (uint16_t)temp );
#ifdef STM32F10X
    if( obj->channel == 1 )
        DAC_SetChannel1Data(DAC_Align_12b_R, (uint16_t)temp); /* 12位右对齐数据格式设置DAC值 */
    else
        DAC_SetChannel2Data(DAC_Align_12b_R, (uint16_t)temp); /* 12位右对齐数据格式设置DAC值 */
#elif defined GD32F10X
    dac_data_set( obj->channel, DAC_ALIGN_12B_R, (uint16_t)temp );
    dac_software_trigger_enable( obj->channel );
#endif

    return BSP_SUCCESS;
}


/*********** (C) COPYRIGHT 2020 FiberHome *****END OF FILE****/
